package njust.csc.aecore.utils

import io.github.oshai.kotlinlogging.KotlinLogging
import java.io.IOException
import java.nio.file.Path

private val logger = KotlinLogging.logger {}

/**
 * @Author ZhouHang
 * @Date 24/6/4 周二
 * 动态分析需要的一些命令变量
 */
object CommandUtils {
    private val ADB = listOf("adb")
    val installCmd = ADB + listOf("install")
    val shellCmd = ADB + listOf("shell")
    val amCmd = shellCmd + listOf("am", "start")
    val uninstallCmd = ADB + listOf("uninstall")
    val pullCmd = ADB + listOf("pull")

    /**
     * 阻塞开启进程执行命令，忽略任何输出和错误处理
     * @param cmd 待执行的命令
     * @param log 是否日志记录执行的命令
     * */
    fun runCommand(cmd: List<String>, log: Boolean = true, file: Path? = null) {
        if (log) logger.info { "[exe] ${cmd.joinToString(separator = " ")}" }
        if (file == null) ProcessBuilder(cmd).start().waitFor()
        else {
            val process = ProcessBuilder(cmd).redirectOutput(file.toFile())
            process.start().waitFor()
        }
    }

    /**
     * 针对命令输出的每一行都进行回调函数的处理和判断, 并且执行完成才返回
     * @param cmd 待执行的命令
     * @param log 是否日志记录执行的命令
     * @param callback 对进程输出的每一行进行回调处理，参数为每行的文本
     * */
    fun runCommand(cmd: List<String>, log: Boolean = true, callback: (String) -> Unit) {
        if (log) logger.info { "[exe] ${cmd.joinToString(separator = " ")}" }
        val processBuilder = ProcessBuilder(cmd)
            .redirectErrorStream(true)
        val process = processBuilder.start()
        process.inputStream.bufferedReader().useLines { lines ->
            lines.forEach { line -> callback(line) }
        }
        process.waitFor()
    }
}